home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / UUPC11QS.ARJ / MAILBLIB.C < prev    next >
C/C++ Source or Header  |  1991-10-21  |  37KB  |  1,032 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    Support routines for UUPC/extended mail user agent              */
  3. /*                                                                    */
  4. /*    History:                                                        */
  5. /*                                                                    */
  6. /*    12 Feb 1991    Created for 1.09d                   ahd          */
  7. /*--------------------------------------------------------------------*/
  8.  
  9. /*--------------------------------------------------------------------*/
  10. /*                           include files                            */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <ctype.h>
  17.  
  18. #include "lib.h"
  19. #include "mail.h"
  20. #include "maillib.h"
  21. #include "mailblib.h"
  22. #include "mailsend.h"
  23. #include "hlib.h"
  24. #include "alias.h"
  25. #include "expath.h"
  26.  
  27. /*--------------------------------------------------------------------*/
  28. /*                      Variables global to file                      */
  29. /*--------------------------------------------------------------------*/
  30.  
  31. static int *item_list = NULL;
  32. static size_t next_item;
  33.  
  34. currentfile();
  35.  
  36. /*--------------------------------------------------------------------*/
  37. /*                    Internal function prototypes                    */
  38. /*--------------------------------------------------------------------*/
  39.  
  40. static boolean SearchUser( char *token , char **input, const int bits);
  41.  
  42. static boolean SearchSubject( char *token,
  43.                               char **input,
  44.                               char *trailing,
  45.                               const int bits);
  46.  
  47. /*--------------------------------------------------------------------*/
  48. /*                     Externally known functions                     */
  49. /*--------------------------------------------------------------------*/
  50.  
  51. /*--------------------------------------------------------------------*/
  52. /*    S h o w A l i a s                                               */
  53. /*                                                                    */
  54. /*    Print the expansion of an alias                                 */
  55. /*--------------------------------------------------------------------*/
  56.  
  57. void ShowAlias( const char *alias)
  58. {
  59.    char *fullname = AliasByNick( alias );
  60.    static int level = 0;
  61.    int column = level * 2;
  62.  
  63.    if ( alias == NULL )
  64.    {
  65.       printf("Missing operand\n");
  66.       return;
  67.    }
  68.  
  69. /*--------------------------------------------------------------------*/
  70. /*                        Indent nested calls                         */
  71. /*--------------------------------------------------------------------*/
  72.  
  73.    while(column-- > 0 )
  74.       putchar(' ');
  75.  
  76.    level++;                   /* Bump up a level for recursive calls */
  77.  
  78. /*--------------------------------------------------------------------*/
  79. /*       Show the alias, breaking it down recursively if need be      */
  80. /*--------------------------------------------------------------------*/
  81.  
  82.    if (fullname == NULL)
  83.       printf("No alias defined for \"%s\"\n",alias);
  84.    else {
  85.       printf("%s is aliased to %s\n",alias,fullname);
  86.       if (*fullname != '"')
  87.       {
  88.          char buf[LSIZE];
  89.          strcpy( buf, fullname );
  90.          fullname = strtok( buf , " ," );
  91.          while (fullname != NULL )
  92.          {
  93.             char *save = strtok( NULL , "");
  94.             ShowAlias(fullname);
  95.             fullname = strtok( save , " ," );
  96.          } /* while */
  97.       } /* if */
  98.    } /* else */
  99.  
  100.    level--;                   /* Restore indent level                */
  101. } /* ShowAlias */
  102.  
  103. /*--------------------------------------------------------------------*/
  104. /*    S a v e I t e m                                                 */
  105. /*                                                                    */
  106. /*    Save an item in another mailbox                                 */
  107. /*--------------------------------------------------------------------*/
  108.  
  109. boolean SaveItem( const int item,
  110.                const boolean delete,
  111.                const copyopt headers,
  112.                char *fname,
  113.                const ACTION verb)
  114. {
  115.    char filename[FILENAME_MAX];
  116.    char *s = "?";
  117.    FILE *stream;
  118.  
  119.    if (fname == NULL)
  120.       fname = "~/MBOX";
  121.  
  122. /*--------------------------------------------------------------------*/
  123. /*                        Build the file name                         */
  124. /*--------------------------------------------------------------------*/
  125.  
  126.    switch (*fname)
  127.    {
  128.       case '=':         /* relative to home directory? */
  129.             printf("Syntax is obsolete ... use \"~/%s\"", fname + 1 );
  130.             mkfilename(filename, homedir, ++fname);
  131.             break;
  132.  
  133.       case '+':         /* Relative to mail directory?   */
  134.             mkmailbox(filename, ++fname);
  135.             break;
  136.  
  137.       default:
  138.       case '~':         /* Relative to home directory?            */
  139.             strcpy( filename , fname );
  140.             if (expand_path( filename , NULL, homedir, E_mailext ) == NULL)
  141.                return FALSE;
  142.             break;
  143.    }  /* end switch */
  144.  
  145. /*--------------------------------------------------------------------*/
  146. /*               Announce our action based on the verb                */
  147. /*--------------------------------------------------------------------*/
  148.  
  149.    switch( verb )
  150.    {
  151.       case M_COPY:
  152.          s = "Copying";
  153.          break;
  154.  
  155.       case M_SAVE:
  156.          s = "Saving";
  157.          break;
  158.  
  159.       case M_WRITE:
  160.          s = "Writing";
  161.          break;
  162.    } /* switch */
  163.  
  164.    printf("%s item %d to %s\n", s , item + 1, filename );
  165.  
  166. /*--------------------------------------------------------------------*/
  167. /*                     Open the mailox to save to                     */
  168. /*--------------------------------------------------------------------*/
  169.  
  170.    if ((stream = FOPEN(filename, "a", TEXT)) == nil(FILE))
  171.    {
  172.       printf("Cannot append to %s\n", filename);
  173.       return FALSE;
  174.    } /* if */
  175.  
  176.    CopyMsg(item, stream, headers, FALSE);
  177.    fclose(stream);
  178.  
  179. /*--------------------------------------------------------------------*/
  180. /*                   Delete the message if required                   */
  181. /*--------------------------------------------------------------------*/
  182.  
  183.    if (letters[item].status < M_DELETED)
  184.       letters[item].status = delete ? M_DELETED : M_SAVED;
  185.  
  186.    return TRUE;
  187. } /* SaveItem */
  188.  
  189.  
  190. /*--------------------------------------------------------------------*/
  191. /*    P o s i t i o n                                                 */
  192. /*                                                                    */
  193. /*    Makes reasonable choice of next letter to examine               */
  194. /*--------------------------------------------------------------------*/
  195.  
  196. int Position(int absolute, int relative, int start)
  197. {
  198.    int current = start;
  199.  
  200. /*--------------------------------------------------------------------*/
  201. /*                   Explicitly position the letter                   */
  202. /*--------------------------------------------------------------------*/
  203.  
  204.    if ( absolute )
  205.    {
  206.       current = absolute ;
  207.       if (( current <= letternum ) && (current > 0))
  208.          return current - 1;
  209.       else if ( current >= letternum )
  210.          printf("Item %d does not exist, last item in mailbox is %d\n",
  211.                current , letternum);
  212.       else
  213.          printf("Cannot backup beyond top of mailbox\n");
  214.  
  215.       return start;
  216.    } /* if */
  217.  
  218. /*--------------------------------------------------------------------*/
  219. /*           Position the pionter relative to current item            */
  220. /*--------------------------------------------------------------------*/
  221.  
  222.    if ( relative )
  223.    {
  224.       int move ;
  225.       move = (relative > 0) ? 1 : -1;
  226.       if ( (current + move) == letternum )
  227.       {
  228.          printf("At end of mailbox\n");
  229.          return current;
  230.       }
  231.  
  232.       while ( relative )
  233.       {
  234.          current += move;
  235.          if ( current >= letternum )
  236.          {
  237.             printf("Item %d does not exist, last item in mailbox is %d\n",
  238.                   current+relative, letternum);
  239.             return start;
  240.          }
  241.          else if ( current < 0 )
  242.          {
  243.             printf("Cannot backup beyond top of mailbox\n");
  244.             return start;
  245.          }
  246.          else if (letters[current].status != M_DELETED)
  247.             relative -= move;
  248.       } /* while */
  249.  
  250.       return current;
  251.    } /* if */
  252.  
  253. /*--------------------------------------------------------------------*/
  254. /*                   Implicitly position the letter                   */
  255. /*--------------------------------------------------------------------*/
  256.  
  257.    while (current < letternum)
  258.    {
  259.       if (letters[current].status != M_DELETED)
  260.          return current;
  261.       else
  262.          ++current;
  263.    } /* while */
  264.  
  265.    current = start;
  266.  
  267.    while (current-- > 0)
  268.       if (letters[current].status != M_DELETED)
  269.          return current;
  270.  
  271.    printf("At end of mailbox\n");
  272.    return start;
  273. } /* Position */
  274.  
  275. /*--------------------------------------------------------------------*/
  276. /*    D e l i v e r M a i l                                           */
  277. /*                                                                    */
  278. /*    Compose interactive outgoing mail                               */
  279. /*--------------------------------------------------------------------*/
  280.  
  281. boolean DeliverMail( char *addresses , int item)
  282. {
  283.    char *Largv[MAXADDRS];
  284.    int   Largc;
  285.  
  286.    Largc = getargs(addresses , Largv );
  287.    return Collect_Mail(stdin, Largc , Largv, item , FALSE);
  288. } /* DeliverMail */
  289.  
  290. /*--------------------------------------------------------------------*/
  291. /*    R e p l y                                                       */
  292. /*                                                                    */
  293. /*    Reply to incoming mail                                          */
  294. /*--------------------------------------------------------------------*/
  295.  
  296. boolean Reply( const int current )
  297. {
  298.    char *Largv[MAXADDRS];
  299.    char subject[LSIZE];
  300.    char addr[LSIZE];
  301.    char line[LSIZE];
  302.    char *column;
  303.    int   Largc = 0;
  304.  
  305.    subject[0] = '\0';
  306.  
  307. /*--------------------------------------------------------------------*/
  308. /*               Determine if we can reply to the mail                */
  309. /*--------------------------------------------------------------------*/
  310.  
  311.    if (!RetrieveLine(letters[current].replyto, addr, LSIZE))
  312.    {
  313.       printf("Cannot determine return address\n");
  314.       return FALSE;
  315.    }
  316.  
  317. /*--------------------------------------------------------------------*/
  318. /*                  Get the incoming subject, if any                  */
  319. /*--------------------------------------------------------------------*/
  320.  
  321.    if (RetrieveLine(letters[current].subject, line, LSIZE))
  322.    {
  323.       register char  *sp = line;
  324.  
  325.       while (!isspace(*sp))     /* Skip "Subject:"      */
  326.          sp++;
  327.       while (isspace(*sp))      /* Skip leading whitespace */
  328.          sp++;
  329.       Largv[Largc++] = "-s";
  330.  
  331.       if (!equalni(sp,"Re:",3))
  332.          strcat(subject,"Re: ");
  333.       strcat(subject,sp);
  334.       Largv[Largc++] = subject;
  335.    }
  336.  
  337. /*--------------------------------------------------------------------*/
  338. /*                   Get the extract return address                   */
  339. /*--------------------------------------------------------------------*/
  340.  
  341.    column = addr;
  342.    while (!isspace(*column) && strlen(column))
  343.       column++;
  344.  
  345.    BuildAddress(line,column);      /* Build standard "To:" addr  */
  346.    printf("Replying to %s\n", line);
  347.  
  348. /*--------------------------------------------------------------------*/
  349. /*                    Format the outgoing address                     */
  350. /*--------------------------------------------------------------------*/
  351.  
  352.    Largv[Largc++] = line;
  353.  
  354.    if (letters[current].status < M_ANSWERED)
  355.       letters[current].status = M_ANSWERED;
  356.  
  357.    return Collect_Mail(stdin, Largc, Largv, current, TRUE);
  358.  
  359. } /* Reply */
  360.  
  361.  
  362. /*--------------------------------------------------------------------*/
  363. /*    F o r w a r d I t e m                                           */
  364. /*                                                                    */
  365. /*    Forward (resend) mail to another address                        */
  366. /*--------------------------------------------------------------------*/
  367.  
  368. boolean ForwardItem( const int item , const char *string )
  369. {
  370.    FILE *stream;
  371.    char  *Largv[MAXADDRS];
  372.    char buf[LSIZE];
  373.    char tmailbag[FILENAME_MAX];
  374.    int   Largc;
  375.    boolean success;
  376.  
  377. /*--------------------------------------------------------------------*/
  378. /*              copy current message to a temporary file              */
  379. /*--------------------------------------------------------------------*/
  380.  
  381.    mktempname(tmailbag, "TMP");
  382.    stream = FOPEN(tmailbag, "w", TEXT);
  383.    if (stream == NULL )
  384.    {
  385.       perror(tmailbag);
  386.       return FALSE;
  387.    } /* if */
  388.  
  389.    CopyMsg(item, stream, noreceived,FALSE);
  390.  
  391.    fclose(stream);
  392.  
  393. /*--------------------------------------------------------------------*/
  394. /*               mail the content of the temporary file               */
  395. /*--------------------------------------------------------------------*/
  396.  
  397.    stream = FOPEN(tmailbag, "r", TEXT);
  398.    if (stream == NULL )
  399.    {
  400.       perror(tmailbag);
  401.       panic();
  402.    }
  403.  
  404.    strcpy( buf , string );
  405.    Largc = getargs( buf , Largv );
  406.    success = Send_Mail(stream, Largc , Largv, NULL, TRUE);
  407.  
  408. /*--------------------------------------------------------------------*/
  409. /*                   Clean up and return to caller                    */
  410. /*--------------------------------------------------------------------*/
  411.  
  412.    if (letters[item].status < (int) M_FORWARDED)
  413.       letters[item].status = (int) M_FORWARDED;
  414.    remove(tmailbag);
  415.  
  416.    return success;
  417. } /* ForwardItem */
  418.  
  419.  
  420. /*--------------------------------------------------------------------*/
  421. /*    s u b s h e l l                                                 */
  422. /*                                                                    */
  423. /*    Invoke inferior command processor                               */
  424. /*--------------------------------------------------------------------*/
  425.  
  426. void subshell( char *command )
  427. {
  428.    if ( command == NULL )
  429.    {
  430.       char *new_prompt;
  431.  
  432.       char *exit_prompt =  "PROMPT=Enter EXIT to return to MAIL$_";
  433.       char *old_prompt;
  434.  
  435.       old_prompt = getenv( "PROMPT" );
  436.       if ( old_prompt == NULL )
  437.          old_prompt = "$p$g";
  438.  
  439.       new_prompt = malloc( strlen( old_prompt ) + strlen( exit_prompt ) + 1);
  440.       checkref( new_prompt );
  441.  
  442.       strcpy( new_prompt , exit_prompt );
  443.       strcat( new_prompt, old_prompt );
  444.  
  445.       if (putenv( new_prompt ) )
  446.       {
  447.          printmsg(0,"Prompt update failed ...");
  448.          printerr("putenv");
  449.       }
  450.  
  451.       system( getenv( "COMSPEC" ) );
  452.    } /* if */
  453.    else
  454.       system ( command );
  455. } /* subshell */
  456.  
  457. /*--------------------------------------------------------------------*/
  458. /*    S e l e c t I t e m s                                           */
  459. /*                                                                    */
  460. /*    Select mail items to be processed by the current command        */
  461. /*--------------------------------------------------------------------*/
  462.  
  463. boolean SelectItems( char **input, int current , int bits)
  464. {
  465.    char *next_token = *input;
  466.    char *token = NULL;
  467.    char trailing[LSIZE];      /* for saving trailing part of line    */
  468.    int item;
  469.    boolean hit = FALSE;
  470.  
  471. /*--------------------------------------------------------------------*/
  472. /*                 Reset all mail items to unselected                 */
  473. /*--------------------------------------------------------------------*/
  474.  
  475.    next_item = 0;
  476.  
  477. /*--------------------------------------------------------------------*/
  478. /*            If no operands, return the current mail item            */
  479. /*--------------------------------------------------------------------*/
  480.  
  481.    if ( *input == NULL )
  482.    {
  483.       SetItem( current+1 );
  484.       return SetTrailing( input , bits );
  485.    }
  486.  
  487. /*--------------------------------------------------------------------*/
  488. /*             Select all items if the user requested so              */
  489. /*--------------------------------------------------------------------*/
  490.  
  491.    strcpy( trailing , next_token );
  492.    token = strtok( next_token , WHITESPACE );
  493.    if (equal(token,"*"))      /* Select all items?                   */
  494.    {
  495.       *input = strtok( NULL , "" );
  496.  
  497.       for ( item = 1; item <= letternum; item++)
  498.          SetItem( item );
  499.  
  500.       return SetTrailing( input , bits );
  501.    } /* if */
  502.  
  503. /*--------------------------------------------------------------------*/
  504. /*   If the first token begins with a slash (/), scan for items       */
  505. /*   with the subject.                                                */
  506. /*--------------------------------------------------------------------*/
  507.  
  508.    if ( *token == '/' )
  509.       return SearchSubject( token, input, trailing, bits);
  510.  
  511. /*--------------------------------------------------------------------*/
  512. /*          Scan the line until we hit a non-numeric operand          */
  513. /*--------------------------------------------------------------------*/
  514.  
  515.    while ( token != NULL)
  516.    {
  517.       boolean success = TRUE;
  518.       next_token = strtok( NULL , "");
  519.                               /* Remember next of line for next pass */
  520.  
  521.       if (Numeric( token ))
  522.          hit = success = SetItem( atoi(token) );
  523.       else if (equal( token, "$"))
  524.          hit = success = SetItem( letternum );
  525.       else if (equal( token, "."))
  526.          hit = success = SetItem( current + 1 );
  527.       else if (strpbrk(token,"@!") != NULL ) /* User id?             */
  528.          break;                  /* Yes --> Exit loop gracefully     */
  529.       else if (isdigit(*token) || (*token == '$') || (*token == '.'))
  530.                                  /* Is it start-end combination?     */
  531.       {                          /* Yes --> Handle it                */
  532.          char *start, *end ;
  533.          int  istart, iend;
  534.          start = strtok( token , "-");
  535.          end   = strtok( NULL , "");
  536.  
  537.          if (equal(start,"$"))
  538.             istart = letternum;
  539.          else if (equal(start,"."))
  540.             istart = current + 1 ;
  541.          else if (!Numeric( start ))
  542.          {
  543.             printf("%s: Operand is not numeric\n", start );
  544.             return FALSE;
  545.          } /* if */
  546.          else
  547.             istart = atoi( start );
  548.  
  549.          if ( (end == NULL) )
  550.          {
  551.             printf("Missing end of item range\n" );
  552.             return FALSE;
  553.          } /* if */
  554.  
  555.          if (equal(end,"$"))
  556.             iend = letternum;
  557.          else if (equal(end,"."))
  558.             iend = current + 1 ;
  559.          else if (!Numeric( end ))
  560.          {
  561.             printf("%s: Operand is not numeric\n", end );
  562.             return FALSE;
  563.          } /* if */
  564.          else
  565.             iend = atoi( end );
  566.  
  567.          if ( iend < istart)
  568.          {
  569.             printf("Ending item (%d) is less than starting item (%d)\n",
  570.                    iend , istart );
  571.             return FALSE;
  572.          } /* if */
  573.  
  574.          for ( item = istart; (item <= iend) && success; item++ )
  575.             hit = success = SetItem ( item );
  576.  
  577.       } /* else */
  578.       else
  579.          break ;
  580.  
  581.       if ( !success )
  582.          return FALSE;
  583.  
  584.       if ( next_token != NULL )
  585.       {
  586.          strcpy( trailing , next_token );
  587.                               /* Save current line so we can back up */
  588.          token = strtok( next_token, WHITESPACE );
  589.       }
  590.       else
  591.          token = NULL;
  592.    } /* while */
  593.  
  594. /*--------------------------------------------------------------------*/
  595. /*   Determine if we have a user id to search for.  This is harder    */
  596. /*   than the above search for subject lines, because the user id     */
  597. /*   doesn't have to have a special delimiter; thus, we do our        */
  598. /*   best to discard other types of items and assume a user id        */
  599. /*   only if we don't know what it is.                                */
  600. /*--------------------------------------------------------------------*/
  601.  
  602.    if ( ! hit )
  603.    {
  604.       if ( (bits & (FILE_OP | USER_OP)) == 0x0000)
  605.       {
  606.          *input = next_token;
  607.          return SearchUser( token, input, bits);
  608.       }
  609.       else if ((bits & USER_OP) == 0x0000)
  610.       {
  611.          if ((strpbrk(token,"@%!") != NULL) || (next_token != NULL))
  612.          {
  613.             *input = next_token;
  614.             return SearchUser( token, input, bits);
  615.          }
  616.       }
  617.    } /* if (! hit) */
  618.  
  619. /*--------------------------------------------------------------------*/
  620. /*      Handle trailing operands when user selected items by number   */
  621. /*--------------------------------------------------------------------*/
  622.  
  623.    if ( token != NULL )
  624.    {
  625.       if (!hit)               /* Any numeric operands?               */
  626.          SetItem( current+1 );   /* No --> Set current as default    */
  627.       strcpy( *input, trailing );
  628.    }
  629.    else
  630.       *input = NULL ;
  631.  
  632.    return SetTrailing( input , bits );
  633.  
  634. } /* SelectItems */
  635.  
  636.  
  637. /*--------------------------------------------------------------------*/
  638. /*    S e a r c h S u j e c t                                         */
  639. /*                                                                    */
  640. /*    Search for mail items to select by the subject                  */
  641. /*--------------------------------------------------------------------*/
  642.  
  643. static boolean SearchSubject( char *token,
  644.                               char **input,
  645.                               char *trailing,
  646.                               const int bits)
  647. {
  648.    char line[LSIZE];
  649.    int item;
  650.    char *next_token;
  651.    boolean hit = FALSE;
  652.  
  653.    token = strtok(trailing,"/");    /* Get subject to search      */
  654.    if ( token == NULL )
  655.    {
  656.       printf("Missing subject to search for\n");
  657.       return FALSE;
  658.    }
  659.    token = strlwr(token);  /* Case insensitive search             */
  660.    next_token = strtok(NULL,"");
  661.                            /* Get rest of line                    */
  662.    for ( item = 1; item <= letternum; item++)
  663.    {
  664.       if (letters[item-1].status == M_DELETED)
  665.          continue;
  666.       if (
  667.            RetrieveLine(letters[item-1].subject, line, LSIZE ) &&
  668.           strstr( strlwr(line), token ))
  669.                            /* This item have subject?             */
  670.       {
  671.          SetItem( item );
  672.          hit = TRUE;
  673.       } /* if */
  674.    } /* for */
  675.  
  676.    if (hit)                /* Did we find the string for user?    */
  677.    {
  678.       if ( next_token == NULL )
  679.          *input = NULL;
  680.       else
  681.          strcpy( *input, next_token );
  682.       return SetTrailing( input , bits ); /* Yes --> Success      */
  683.    } /* if (hit) */
  684.    else {
  685.       printf("No mail items found with subject \"%s\"\n",token);
  686.       return FALSE;
  687.    }  /* else */
  688. } /* SearchSubject */
  689.  
  690.  
  691. /*--------------------------------------------------------------------*/
  692. /*    S e a r c h U s e r                                             */
  693. /*                                                                    */
  694. /*    Search for a user id on mail items                              */
  695. /*--------------------------------------------------------------------*/
  696.  
  697. static boolean SearchUser( char *token , char **input, const int bits)
  698. {
  699.    char line[LSIZE];
  700.    int item;
  701.    boolean hit = FALSE;
  702.  
  703.    token = strlwr(token);  /* Case insensitive search          */
  704.  
  705. /*--------------------------------------------------------------------*/
  706. /*    Our loop is as follows for each item in the mailbox:            */
  707. /*                                                                    */
  708. /*       If the letter is deleted, ignore it                          */
  709. /*       If the From line can be retrieved from the item:             */
  710. /*                                                                    */
  711. /*          1) Read the line                                          */
  712. /*          2) Scan up to the first whitespace                        */
  713. /*             2a) If there is no whitespace, use entire line         */
  714. /*             2b) If there is whitespace, step past it to next       */
  715. /*                 non-whitespace character                           */
  716. /*          3) Lowercase the line                                     */
  717. /*          4) Scan for the the target address in the line:           */
  718. /*             4a) If found select the item for processing            */
  719. /*             4b) If not found, build a standard outgoing address    */
  720. /*                 and search again.  If found, select the item       */
  721. /*                                                                    */
  722. /*       If the From line cannot be retrieved:                        */
  723. /*          1) call ReturnAddress to format the return address        */
  724. /*             (Because the line cannot be retrieved, it will         */
  725. /*              "-- unknown --", the same string displayed by         */
  726. /*              Headers.                                              */
  727. /*          2) Scan for the the target address in the returned        */
  728. /*             address                                                */
  729. /*          3) If found, select the item for processing               */
  730. /*--------------------------------------------------------------------*/
  731.  
  732.    for ( item = 1; item <= letternum; item++)
  733.    {
  734.       printmsg(2,"Examining item %d", item);
  735.       if (letters[item-1].status == M_DELETED)
  736.          continue;
  737.       if (RetrieveLine(letters[item - 1].from, line, LSIZE))
  738.       {
  739.          char *addr  = strpbrk(line,WHITESPACE);
  740.          if (addr == NULL)    /* Whitespace in input line?        */
  741.             addr = line;      /* No --> Use entire line           */
  742.          else
  743.             while(isspace(*addr))   /* Yes --> Skip past first WS */
  744.                addr++;
  745.          printmsg(2,"SearchUser: Address %d is: %s",item-1,addr);
  746.          if ( strstr( strlwr(addr), token ))    /* Find address?  */
  747.             hit = SetItem( item );  /* Yes--> Select item for use */
  748.          else {                     /* No--> Expand & search again*/
  749.             char result[MAXADDR];
  750.             BuildAddress( result, addr);
  751.                            /* Get expanded address for user       */
  752.             printmsg(2,"SearchUser: Formatted address %d is: %s",
  753.                   item-1,result);
  754.             if ( strstr( strlwr(result), token ))
  755.                            /* This item have correct sender?      */
  756.                hit = SetItem( item );  /* Yes --> Set it          */
  757.             else
  758.                printmsg(2,"SearchUser: Item %d not selected.",
  759.                      item-1);
  760.          } /* else */
  761.       } /* if */
  762.       else {
  763.          ReturnAddress(line,&letters[item - 1]);
  764.                            /* Get standard error text for letter  */
  765.          printmsg(2,"SearchUser: Default address %d is: %s",
  766.                   item-1,line);
  767.          if ( strstr( strlwr(line), token ))
  768.                            /* This item have correct sender?      */
  769.             hit = SetItem( item );  /* Yes --> Set it             */
  770.       } /* else */
  771.    } /* for */
  772.  
  773. /*--------------------------------------------------------------------*/
  774. /*        End of loop; determined success and return to caller        */
  775. /*--------------------------------------------------------------------*/
  776.  
  777.    if (hit)             /* Did we find the string for user?    */
  778.       return SetTrailing( input , bits ); /* Yes --> Success   */
  779.    else {
  780.       printf("No mail items found from \"%s\"\n",token);
  781.       return FALSE;
  782.    }  /* else */
  783.  
  784. }  /* SearchUser */
  785.  
  786.  
  787. /*--------------------------------------------------------------------*/
  788. /*    S e t T r a i l i n g                                           */
  789. /*                                                                    */
  790. /*    Determine success of command parse based on trailing operands   */
  791. /*--------------------------------------------------------------------*/
  792.  
  793. boolean SetTrailing( char **input, int bits )
  794. {
  795.  
  796. /*--------------------------------------------------------------------*/
  797. /*                        Trim trailing spaces                        */
  798. /*--------------------------------------------------------------------*/
  799.  
  800.    if (*input != NULL)
  801.    {
  802.       char *s = *input;
  803.       while( isspace(*s))
  804.          s++;
  805.       if ( *s == '\0' )       /* Anything left in string?            */
  806.          *input = NULL;       /* No --> Flag input as NULL           */
  807.       else
  808.          *input = s;          /* Yes --> Point input to next operand */
  809.    }
  810.  
  811. /*--------------------------------------------------------------------*/
  812. /*                     Trailing address operands?                     */
  813. /*--------------------------------------------------------------------*/
  814.  
  815.    if (( bits & USER_OP ) || ( *input == NULL ))
  816.       return TRUE;            /* Let Get_Operand check operands      */
  817.  
  818. /*--------------------------------------------------------------------*/
  819. /*                        Trailing file name?                         */
  820. /*--------------------------------------------------------------------*/
  821.  
  822.    if ( bits & FILE_OP )
  823.    {
  824.       char *token = strtok( *input , WHITESPACE );
  825.       token = strtok( NULL , "" );
  826.  
  827.       if ( token == NULL )
  828.          return TRUE;
  829.       else {
  830.          printf("%s: Only one file operand allowed on command\n",
  831.             token);
  832.          return FALSE;
  833.       } /* else */
  834.    } /* if */
  835.  
  836. /*--------------------------------------------------------------------*/
  837. /*                   No operand allowed; reject it                    */
  838. /*--------------------------------------------------------------------*/
  839.  
  840.    printf("%s: Unknown operand on command\n", *input);
  841.    return FALSE;
  842.  
  843. } /* SetTrailing */
  844.  
  845. /*--------------------------------------------------------------------*/
  846. /*    S e t I t e m                                                   */
  847. /*                                                                    */
  848. /*    Validate and select a single item                               */
  849. /*--------------------------------------------------------------------*/
  850.  
  851. boolean SetItem( int item )
  852. {
  853.    if ( item_list == NULL )
  854.    {
  855.       item_list = calloc( letternum, sizeof *item_list);
  856.       checkref( item_list );
  857.    }
  858.  
  859.    if ((item > 0) && ( item <= letternum ))
  860.    {
  861.       item_list[ next_item++ ] = item - 1;
  862.       return TRUE;
  863.    }
  864.    else {
  865.       printf("Invalid item (%d) selected for processing\n",item);
  866.       return FALSE;
  867.    } /* else */
  868. } /* SetItem */
  869.  
  870. /*--------------------------------------------------------------------*/
  871. /*    G e t _ O p e r a n d                                           */
  872. /*                                                                    */
  873. /*    Get next operand to process                                     */
  874. /*--------------------------------------------------------------------*/
  875.  
  876. boolean Get_Operand( int *item,
  877.                      char **token,
  878.                      int bits,
  879.                      boolean first_pass )
  880. {
  881.  
  882. /*--------------------------------------------------------------------*/
  883. /*                         Handle no operand                          */
  884. /*--------------------------------------------------------------------*/
  885.  
  886.    if (bits & NO_OPERANDS)
  887.    {
  888.       if ( *token == NULL )
  889.          return first_pass;
  890.       else {
  891.          printf("Operands not allowed on this command!\n");
  892.          return FALSE;
  893.       } /* else */
  894.    }
  895.  
  896. /*--------------------------------------------------------------------*/
  897. /*        User operands are like string operands, but required        */
  898. /*--------------------------------------------------------------------*/
  899.  
  900.    if ( (bits & USER_OP) && (*token == NULL))
  901.    {
  902.       printf("Missing addressees for command\n");
  903.       return FALSE;
  904.    }
  905. /*--------------------------------------------------------------------*/
  906. /*                       Handle letter operand                        */
  907. /*--------------------------------------------------------------------*/
  908.  
  909.    if ( bits & LETTER_OP )
  910.    {
  911.       static size_t subscript;
  912.       subscript = first_pass ? 0 : subscript + 1;
  913.  
  914.       if (subscript < next_item)
  915.       {
  916.          *item = item_list[subscript];
  917.          return TRUE;
  918.       } /* else */
  919.       else {
  920.          free( item_list );
  921.          item_list = NULL;
  922.          return FALSE;
  923.       } /* else */
  924.    } /* if*/
  925.  
  926. /*--------------------------------------------------------------------*/
  927. /*                   Handle string operands                           */
  928. /*--------------------------------------------------------------------*/
  929.  
  930.    if ( bits & (STRING_OP | USER_OP))
  931.    {
  932.       char *buf = *token;
  933.       if (first_pass &&
  934.           (buf != NULL) &&
  935.           ( buf[ strlen(buf) - 1 ] == '\n'))
  936.          buf[ strlen(buf) - 1 ] = '\0';
  937.       return first_pass;
  938.    }
  939.  
  940. /*--------------------------------------------------------------------*/
  941. /*                     Handle tokenized operands                      */
  942. /*--------------------------------------------------------------------*/
  943.  
  944.    if ( bits & TOKEN_OP )
  945.    {
  946.       static char *rest = NULL ;
  947.       if (first_pass)
  948.          rest = *token;
  949.  
  950.       if ( *rest == (char ) NULL)
  951.       {
  952.          *token = NULL;
  953.          return first_pass;
  954.       } /* if */
  955.  
  956.       *token = strtok( rest , WHITESPACE );
  957.       if ( *token == (char) NULL)
  958.       {
  959.          rest = NULL;
  960.          return first_pass;
  961.       }
  962.       else {
  963.          rest = strtok( NULL , "" );
  964.          return TRUE;
  965.       } /* else */
  966.    } /* if */
  967.  
  968. /*--------------------------------------------------------------------*/
  969. /*                      Handle integer operands                       */
  970. /*--------------------------------------------------------------------*/
  971.  
  972.    if ( bits & INTEGER_OP)
  973.    {
  974.       char *p;
  975.       if ( (*token == NULL) || ! first_pass )
  976.       {
  977.          *item = 1;
  978.          return first_pass;
  979.       }
  980.       p = strtok( *token, WHITESPACE );
  981.  
  982.       if (!Numeric( p ))
  983.       {
  984.          printf("%s: Operand is not numeric\n", p );
  985.          return FALSE;
  986.       } /* if */
  987.  
  988.       *item = atoi( p );
  989.       p = strtok( NULL, WHITESPACE );
  990.       if (p != NULL )
  991.       {
  992.          printf("%s: extra operand not allowed on command\n", p);
  993.          return FALSE;
  994.       }
  995.       return TRUE;
  996.    } /* if */
  997.  
  998. /*--------------------------------------------------------------------*/
  999. /*                   We cannot handle this command                    */
  1000. /*--------------------------------------------------------------------*/
  1001.  
  1002.    printf("Unknown processing option = %x, cannot process command\n",
  1003.          bits);
  1004.    return FALSE;
  1005.  
  1006. } /* Get_Operand */
  1007.  
  1008. /*--------------------------------------------------------------------*/
  1009. /*    P u s h I t e m L i s t                                         */
  1010. /*                                                                    */
  1011. /*    Save item parsing list                                          */
  1012. /*--------------------------------------------------------------------*/
  1013.  
  1014. int PushItemList( int **save_list )
  1015. {
  1016.    *save_list = item_list;
  1017.    item_list = NULL;
  1018.    return next_item;
  1019. } /* PushItemList */
  1020.  
  1021. /*--------------------------------------------------------------------*/
  1022. /*    P o p I t e m L i s t                                           */
  1023. /*                                                                    */
  1024. /*    Restore parsing information saved by PushItemList               */
  1025. /*--------------------------------------------------------------------*/
  1026.  
  1027. void PopItemList( int *save_list, int save_item )
  1028. {
  1029.    item_list = save_list;
  1030.    next_item = save_item;
  1031. } /* PopItemList */
  1032.